/**
 * @FilePath     : /src/lgmg_robots/agv_navigation/agv_navigate/include/agvWorld/timestamp.h
 * @Description  : 时间戳管理类和定时触发器的实现。
 *                 提供获取当前时间戳、更新时间戳、判断时间戳是否超时、计算时间差等功能。 
 * @Author       : xiujun.yang
 * @Version      : 1.0.0
 * @LastEditors  : haibo haibo.yang@lgmgim.cn
 * @LastEditTime : 2024-12-19 15:38:08
 * @Copyright (c) 2024 by 临工智能信息科技有限公司, All Rights Reserved. 
**/

#pragma once
#include "tools.h"

class TimeStamp
{
public:
    TimeStamp() : time_point_(GetTickCount()) {}
    explicit TimeStamp(TIME_TYPE time) : time_point_(time) {}

    TIME_TYPE GetTimeStamp() const { return time_point_; }

    // Update the time-stamp
    void Update() { time_point_ = GetTickCount(); }

    // Check whether the time-stamp is up-to-date
    bool IsNew(unsigned long time_diff = 500) const
    {
        return (fabs(GetTickCount() - time_point_) < time_diff);
    }

    bool TimeOut(unsigned long time_diff = 500) const
    {
        return !IsNew(time_diff);
    }

    // 获取两次获取的时间差
    float GetDiffMs() const
    {
        return fabs(GetTickCount() - time_point_);
    }

    TIME_TYPE time_point_;
};
//
// 先stop 在start 判断是否触发一次(且切换一次只会触发一次，想要重复触发，需要再次stop->start)
//
//
struct TimerTriggerOnce : public TimeStamp
{
public:
    TimerTriggerOnce() : is_running_(false), has_triggered_once_(false) {}

    // 触发启动一次
    bool Start()
    {
        std::lock_guard<std::mutex> locker(mutex_);
        if (!is_running_)
        {
            is_running_ = true;
            has_triggered_once_ = false;
            Update();
            DEBUG_WARN_OUT("Start Once");
            return true;
        }
        return false;
    }

    // 关闭运行
    bool Stop()
    {
        std::lock_guard<std::mutex> locker(mutex_);
        if (is_running_)
        {
            is_running_ = false;
            has_triggered_once_ = false;
            DEBUG_WARN_OUT("Stop Once");
            return true;
        }
        Update();
        return false;
    }

    // 判断只是否触发一次
    bool TriggerOnce(uint16_t time_diff = 3000)
    {
        std::lock_guard<std::mutex> locker(mutex_);
        if (is_running_ && !has_triggered_once_)
        {
            has_triggered_once_ = TimeOut(time_diff);
            DEBUG_WARN_OUT("Trigger has_triggered_once_=" << has_triggered_once_
                                                          << ", time_diff=" << time_diff);
            return has_triggered_once_;
        }
        return false;
    }

    // 超时一直触发
    bool TriggerAlways(uint16_t time_diff = 3000)
    {
        std::lock_guard<std::mutex> locker(mutex_);
        if (is_running_)
        {
            has_triggered_once_ = TimeOut(time_diff);
            DEBUG_WARN_OUT("Trigger has_triggered_once_=" << has_triggered_once_
                                                          << ", time_diff=" << time_diff);
            return has_triggered_once_;
        }
        return false;
    }
    void ClearTrigger()
    {
        std::lock_guard<std::mutex> locker(mutex_);
        is_running_ = false;
        has_triggered_once_ = false;
        Update();
        DEBUG_WARN_OUT("ClearTrigger");
    }

private:
    bool is_running_;
    bool has_triggered_once_;
    std::mutex mutex_;
};

// C++11 thread safe
template <typename T>
class DataTimeStamp : public TimeStamp
{
public:
    DataTimeStamp() : data_(T()) { TimeStamp::Update(); }
    explicit DataTimeStamp(T data) { Update(data); }

    void Update(T data)
    {
        data_ = data;
        TimeStamp::Update();
    }

    T Get() const { return data_; }

    T data_;
};
